import concurrent.futures
import threading
import requests
import json
url = 'https://open.bigmodel.cn/api/paas/v4/chat/completions'
#url = 'https://cloud.infini-ai.com/maas/v1/chat/completions'
# Replace with your own API key
model='glm-4-plus'
api_key=''
#model = "qwen2.5-72b-instruct"
file_path = "sft_data_clean800.json"
data = []
with open(file_path,"r",encoding="utf-8") as f:
    data = json.load(f)  # 将 JSONL 行解析为 Python 字典

prompt = '''
你是一位专业且有帮助的AI助手，专注于生成格式化的数据，你的回答需要科学严谨、严格符合输出格式，具体要求如下：

1.**定义：**
    - **该场景的定义：**用户在和大模型进行对话，对话有多轮，大模型只在其中一轮对话中进行了回答，它在这一轮生成了一个可以调用的api。当且仅当它获得了足够调用某个api的信息之后，才会在这一轮回答，并且在获得足够的信息之后应该立即在这一轮回答。
    - **api列表的定义：**api列表里面存有若干可以调用的api，api的'description'字段表示这个api的功能，'parameters'字段'表示调用时应该填入的参数。
    - **user_messages列表的定义：**user_messages列表表示用户提出的若干需求，这些需求可能包含了需要调用的api的参数。
    - **targets列表的定义：**targets列表和user_messages列表的元素一一对应，他们代表了若干轮次的对话，但是targets中只有一个元素不为空，表示到这一轮对话为止，大模型获得了足够的参数可以调用某个api

2.**任务内容：**
    -你会收到一个api列表和一个user_messages列表，还有一个targets列表
    -该场景下，target列表的含义是，其中若干中括号表示大模型对当前对话轮次的推理结果
    -如果当前轮次无需调用api，则该括号(list)内为空，无元素
    -如果当前轮次需要api调用，则该list只包含一个元素，元素内容为调用信息，"name"为api的名称，"arguments"装的是api的各项参数取值
    -在当前场景下，该list只需要调用一个元素，你的任务是丰富这个场景，使得这轮需要调用api的对话中，需要调用多个api，可以是调用同一api多次，或者调用不同api。
    -为了完成这个任务，你可以自己按照格式定义新的api，或者修改user_messages列表中user的需求，然后把targets列表中的回答改成在调用api的那一轮次回答调用多个api

3.**输出格式要求：**
    -你需要输出你的思考过程，最后给出答案。
    -答案的开头需要使用myStartOfMission作为标记，答案的结尾需要使用myEndOfMission
    -答案的格式是一个字典，不要加入其他字符，例如json等

4.**演示示例：**
    -**输入示例：**
{"id": "827", "apis": [{"name": "query_token_balance", "description": "查询指定地址在特定区块链上的代币余额。", "parameters": {"type": "object", "properties": {"product_id": {"type": "string", "description": "钱包的区块链地址"}, "token_contract_address": {"type": "string", "description": "代币的智能合约地址"}, "network": {"type": "string", "description": "区块链网络名称"}, "include_usd_value": {"type": "boolean", "description": "是否包含以美元计算的余额价值", "default": false}, "decimals": {"type": "nteger", "description": "产品是否激活", "default": true}}, "required": ["wallet_address", "token_contract_address", "network"]}}, {"name": "milk_quality_analysis", "description": "分析牛奶的质量，包括成分和卫生指标", "parameters": {"type": "object", "properties": {"fat_content": {"type": "number", "description": "牛奶中的脂肪含量（百分比）"}, "protein_content": {"type": "number", "description": "牛奶中的蛋白质含量（百分比）"}, "lactose_content": {"type": "number", "description": "牛奶中的乳糖含量（百分比）"}, "somatic_cell_count": {"type": "number", "description": "牛奶中的体细胞数（每毫升）"}, "total_bacterial_count": {"type": "number", "description": "牛奶中的总细菌数（每毫升）"}}, "required": ["fat_content", "protein_content", "lactose_content", "somatic_cell_count", "total_bacterial_count"]}}, {"name": "monitor_machine_health", "description": "监控机器设备的健康状态，减少故障和停机时间", "parameters": {"type": "object", "properties": {"machine_id": {"type": "string", "description": "机器设备的唯一标识符"}, "vibration_levels": {"type": "number", "description": "机器运作时的振动幅度"}, "temperature": {"type": "number", "description": "机器运作时的温度"}, "operating_hours": {"type": "number", "description": "机器已连续运行的小时数"}, "include_downtime_analysis": {"type": "boolean", "description": "是否包括停机分析报告"}}, "required": ["machine_id", "vibration_levels", "temperature", "operating_hours", "include_downtime_analysis"]}}], "user_messages": ["你好", "我想查一下钱包地址0x742d35Cc6634C0532925a3b844Bc454e4438f44e在Ethereum网络上，代币合约地址为0x1985365e9f78359a9B6AD760e32412f4a445E862的代币余额，并且需要包含以美元计算的余额价值，代币的小数位数是18。"], {"targets":[[],[{"name": "query_token_balance","arguments": {"wallet_address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "token_contract_address": "0x1985365e9f78359a9B6AD760e32412f4a445E862", "network": "Ethereum", "include_usd_value": true, "decimals": 18}}]]}}
    --**输出示例：**
思考过程...
myStartOfMission{"id": "827", "apis": [{"name": "query_token_balance", "description": "查询指定地址在特定区块链上的代币余额。", "parameters": {"type": "object", "properties": {"product_id": {"type": "string", "description": "钱包的区块链地址"}, "token_contract_address": {"type": "string", "description": "代币的智能合约地址"}, "network": {"type": "string", "description": "区块链网络名称"}, "include_usd_value": {"type": "boolean", "description": "是否包含以美元计算的余额价值", "default": false}, "decimals": {"type": "nteger", "description": "产品是否激活", "default": true}}, "required": ["wallet_address", "token_contract_address", "network"]}}, {"name": "milk_quality_analysis", "description": "分析牛奶的质量，包括成分和卫生指标", "parameters": {"type": "object", "properties": {"fat_content": {"type": "number", "description": "牛奶中的脂肪含量（百分比）"}, "protein_content": {"type": "number", "description": "牛奶中的蛋白质含量（百分比）"}, "lactose_content": {"type": "number", "description": "牛奶中的乳糖含量（百分比）"}, "somatic_cell_count": {"type": "number", "description": "牛奶中的体细胞数（每毫升）"}, "total_bacterial_count": {"type": "number", "description": "牛奶中的总细菌数（每毫升）"}}, "required": ["fat_content", "protein_content", "lactose_content", "somatic_cell_count", "total_bacterial_count"]}}, {"name": "monitor_machine_health", "description": "监控机器设备的健康状态，减少故障和停机时间", "parameters": {"type": "object", "properties": {"machine_id": {"type": "string", "description": "机器设备的唯一标识符"}, "vibration_levels": {"type": "number", "description": "机器运作时的振动幅度"}, "temperature": {"type": "number", "description": "机器运作时的温度"}, "operating_hours": {"type": "number", "description": "机器已连续运行的小时数"}, "include_downtime_analysis": {"type": "boolean", "description": "是否包括停机分析报告"}}, "required": ["machine_id", "vibration_levels", "temperature", "operating_hours", "include_downtime_analysis"]}}], "user_messages": ["你好", "我想查一下钱包地址0x742d35Cc6634C0532925a3b844Bc454e4438f44e在Ethereum网络上，代币合约地址为0x1985365e9f78359a9B6AD760e32412f4a445E862的代币余额，并且需要包含以美元计算的余额价值，代币的小数位数是18。另外，我还想查一下钱包地址bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq在Bitcoin网络上，代币合约地址为0x6B175474E89094C44Da98b954EedeAC495271d0F的代币余额。"], {"targets":[[],[{"name": "query_token_balance","arguments": {"wallet_address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "token_contract_address": "0x1985365e9f78359a9B6AD760e32412f4a445E862", "network": "Ethereum", "include_usd_value": true, "decimals": 18}}, {"name": "query_token_balance","arguments": {"wallet_address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq", "token_contract_address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", "network": "Bitcoin"}}]]}}myEndOfMission

5.**以下是我的正式输入，请开始任务：**
'''

def generate_ans(text_content):
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    }


    data = {
        "model": model,
        "messages": [
            {"role": "system", "content": prompt},
            {"role": "user", "content": text_content}
        ],
        "temperature": 0.3
    }
    response = requests.post(url, headers=headers, json=data, verify=False)
    if response.status_code == 200:
        return response.json()["choices"][0]["message"]['content']
    else:
        print(f"Error: {response.status_code}")
        print(response.content)
        return None
counter = 0
counter_lock = threading.Lock()
target_count = 5000
write_lock = threading.Lock()
def process_item(item):
    print(f"正在处理项 {item.get('id')}")
    
    try:
        # 解析输入输出
        d = eval(item["input"])
        f = eval(item["output"])
        d["targets"] = f
    except Exception as e:
        print(f"解析错误: {e}")
        return None

    # 重试逻辑
    output = None
    for _ in range(3):
        try:
            response = generate_ans(str(d))
            if response:
                # 处理响应内容
                if "myStartOfMission" in response:
                    response = response.split("myStartOfMission")[1]
                if "myEndOfMission" in response:
                    response = response.split("myEndOfMission")[0]
                response = response.replace("true","True")
                response = response.replace("false","False")
                response = response.replace("null","None")
                output = eval(response)
                break
        except Exception as e:
            print(f"处理失败: {e}")
            continue
            
    return output
def process_and_write(item, out_file):
    global counter
    result = process_item(item)
    if result:
        with write_lock:
            out_file.write(json.dumps(result, ensure_ascii=False) + "\n")
            # 原子操作更新计数器
            with counter_lock:
                global counter
                counter += 1
                print(f"当前已生成 {counter} 条数据")
        return True
    return False

# 修改后的主处理逻辑
with open('glm_output1.jsonl', 'a', encoding='utf-8') as out_file:
    while True:
        # 检查是否达到目标
        with counter_lock:
            if counter >= target_count:
                print("已达到目标数据量，停止运行")
                break
        
        # 创建线程池（最大200并发）
        with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
            # 提交任务时检查剩余需要生成的数量
            remaining = target_count - counter
            batch_size = min(remaining, len(data))
            
            # 提交当前批次任务
            futures = []
            for item in data[:batch_size]:  # 只取需要数量的数据
                futures.append(executor.submit(process_and_write, item, out_file))
            
            # 等待当前批次完成
            for future in concurrent.futures.as_completed(futures):
                try:
                    future.result()
                except Exception as e:
                    print(f"处理异常: {e}")
                
            # 检查是否完成
            with counter_lock:
                if counter >= target_count:
                    break

